﻿#if TMP_PRESENT
using System.Collections.Generic;
using TMPro;
using UnityEditor;
using UnityEngine;
using System;
using UnityEngine.UI;
using System.Linq;
using TMPro.EditorUtilities;
using System.Reflection;

namespace UnityDefaultSetting.TextMeshProDefaultSetting.Editor
{
    /// <summary>
    /// 该默认设置脚本用于为TextMeshPro文本组件设置默认Rect大小、字体、大小、对齐方式和颜色
    /// 目前仅适用于TextMeshProUGUI和TextMeshPro,Button,InputField、Dropdown等带有TextMeshPro组件的组件
    /// 可以根据不同的组件加载不同的配置
    /// </summary>
    [InitializeOnLoad]
    public class TextMeshProDefaultFontSetter
    {
        private static TextMeshProDefaultTemplateConfig defaultSettingConfig;

        [MenuItem("GameObject/3D Object/Text - TextMeshPro", false, 30)]
        private static void CreateTextMeshProObjectPerform(MenuCommand command)
        {
            // 执行原生逻辑（需要反射）
            ExecuteOriginalMethod("CreateTextMeshProObjectPerform", command);

            if (defaultSettingConfig == null)
                defaultSettingConfig = Resources.Load<TextMeshProDefaultTemplateConfig>("TextMeshProDefaultTemplateConfig");

            if (defaultSettingConfig.isEnable == false) return;
            
            GameObject activeObj = Selection.activeGameObject;

            TextMeshPro text = activeObj.GetComponentInChildren<TextMeshPro>();

            if (ConditionComponentType(() => text, () =>
            {
                SetTMP_TextDefaultValueDelay(text);

            })) return;
        }

        [MenuItem("GameObject/UI/Text - TextMeshPro", false, 2001)]
        private static void CreateTextMeshProGuiObjectPerform(MenuCommand menuCommand)
        {
            // 执行原生逻辑（需要反射）
            ExecuteOriginalMethod("CreateTextMeshProGuiObjectPerform", menuCommand);

            if (defaultSettingConfig == null)
                defaultSettingConfig = Resources.Load<TextMeshProDefaultTemplateConfig>("TextMeshProDefaultTemplateConfig");

            if (defaultSettingConfig.isEnable == false) return;

            GameObject activeObj = Selection.activeGameObject;

            TextMeshProUGUI text = activeObj.GetComponentInChildren<TextMeshProUGUI>();

            if (ConditionComponentType(() => text, () =>
            {
                SetTMP_TextUGUIDefaultValueDelay(text);

            })) return;
        }

        [MenuItem("GameObject/UI/Button - TextMeshPro", false, 2031)]
        private static void AddButton(MenuCommand menuCommand)
        {
            // 执行原生逻辑（需要反射）
            ExecuteOriginalMethod("AddButton", menuCommand);

            if (defaultSettingConfig == null)
                defaultSettingConfig = Resources.Load<TextMeshProDefaultTemplateConfig>("TextMeshProDefaultTemplateConfig");

            if (defaultSettingConfig.isEnable == false) return;

            GameObject activeObj = Selection.activeGameObject;

            Button button = activeObj.GetComponent<Button>();
            TextMeshProUGUI label = activeObj.GetComponentInChildren<TextMeshProUGUI>();

            if (ConditionComponentType(() => button && label, () =>
            {
                SetTMP_ButtonDefaultValueDelay(button);

            })) return;
        }

        [MenuItem("GameObject/UI/Input Field - TextMeshPro", false, 2037)]
        private static void AddTextMeshProInputField(MenuCommand menuCommand)
        {
            // 执行原生逻辑（需要反射）
            ExecuteOriginalMethod("AddTextMeshProInputField", menuCommand);

            if (defaultSettingConfig == null)
                defaultSettingConfig = Resources.Load<TextMeshProDefaultTemplateConfig>("TextMeshProDefaultTemplateConfig");

            if (defaultSettingConfig.isEnable == false) return;

            GameObject activeObj = Selection.activeGameObject;

            TMP_InputField inputField = activeObj.GetComponent<TMP_InputField>();
            TextMeshProUGUI label = activeObj.GetComponentInChildren<TextMeshProUGUI>();

            if (ConditionComponentType(() => inputField && label, () =>
            {
                SetTMP_InputFieldDefaultValueDelay(inputField);

            })) return;
        }

        [MenuItem("GameObject/UI/Dropdown - TextMeshPro", false, 2036)]
        private static void AddDropdown(MenuCommand menuCommand)
        {
            // 执行原生逻辑（需要反射）
            ExecuteOriginalMethod("AddDropdown", menuCommand);

            if (defaultSettingConfig == null)
                defaultSettingConfig = Resources.Load<TextMeshProDefaultTemplateConfig>("TextMeshProDefaultTemplateConfig");

            if (defaultSettingConfig.isEnable == false) return;

            GameObject activeObj = Selection.activeGameObject;

            TMP_Dropdown dropdown = activeObj.GetComponent<TMP_Dropdown>();
            TextMeshProUGUI label = activeObj.GetComponentInChildren<TextMeshProUGUI>();

            if (ConditionComponentType(() => dropdown && label, () =>
            {
                SetTMP_DropdownDefaultValueDelay(dropdown);

            })) return;
        }

        /// <summary>
        /// 这里的反射依赖与TMPro_CreateObjectMenu方法
        /// </summary>
        /// <param name="methodName"></param>
        /// <param name="menuCommand"></param>
        private static void ExecuteOriginalMethod(string methodName, MenuCommand menuCommand)
        {
            try
            {
                // 获取原生的 AddButton 方法
                Type buttonMenuType = typeof(TMPro_CreateObjectMenu);
                MethodInfo addMethod = buttonMenuType.GetMethod(
                    methodName,
                    BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public
                );

                if (addMethod != null)
                {
                    addMethod.Invoke(null, new object[] { menuCommand });
                }
            }
            catch (Exception e)
            {
                Debug.LogError("无法调用原生 AddButton 方法: " + e.Message);
            }
        }

        private static bool ConditionComponentType(Func<bool> predicate, Action action = null)
        {
            if (predicate.Invoke())
            {
                EditorApplication.delayCall += OnDelayCall;

                void OnDelayCall()
                {
                    action?.Invoke();
                    EditorApplication.delayCall -= OnDelayCall;
                }
                return true;
            }
            return false;
        }

        private static void SetTMP_ButtonDefaultValueDelay(Component component)
        {
            TextMeshProDefaultSettingConfig buttonConfig = defaultSettingConfig.TMP_ButtonTextConfig;
            TMP_Text text = component.GetComponentInChildren<TMP_Text>();

            SetDefaultValueDelay(component, text, buttonConfig);
        }

        private static void SetTMP_DropdownDefaultValueDelay(Component component)
        {
            TextMeshProDefaultSettingConfig dropDownItemTextConfig = defaultSettingConfig.TMP_DropDownItemLabelConfig;
            TextMeshProDefaultSettingConfig dropDownLabelTextConfig = defaultSettingConfig.TMP_DropDownLabelConfig;

            TMP_Dropdown dropdown = component as TMP_Dropdown;

            SetDefaultValueDelay(component, dropdown.itemText, dropDownItemTextConfig);
            SetDefaultValueDelay(component, dropdown.captionText, dropDownLabelTextConfig);
        }

        private static void SetTMP_InputFieldDefaultValueDelay(Component component)
        {
            TextMeshProDefaultSettingConfig inputFieldPlaceholderConfig = defaultSettingConfig.TMP_InputFieldPlaceholderConfig;
            TextMeshProDefaultSettingConfig inputFieldTextConfig = defaultSettingConfig.TMP_InputFieldTextConfig;

            TMP_InputField inputField = component as TMP_InputField;

            SetDefaultValueDelay(component, (TMP_Text)inputField.placeholder, inputFieldPlaceholderConfig);

            SetDefaultValueDelay(component, inputField.textComponent, inputFieldTextConfig);
        }

        private static void SetTMP_TextUGUIDefaultValueDelay(TMP_Text component)
        {
            TextMeshProDefaultSettingConfig settingConfig = defaultSettingConfig.TMP_TextUGUIConfig;
            SetDefaultValueDelay(component, component, settingConfig);
        }

        private static void SetTMP_TextDefaultValueDelay(TMP_Text component)
        {
            TextMeshProDefaultSettingConfig settingConfig = defaultSettingConfig.TMP_TextConfig;
            SetDefaultValueDelay(component, component, settingConfig);
        }

        private static void SetDefaultValueDelay(Component component, TMP_Text textComponent, TextMeshProDefaultSettingConfig settingConfig)
        {
            // 确保颜色设置在所有其他设置之后
            EditorApplication.delayCall += OnDelayCall;

            void OnDelayCall()
            {
                if (component as TMP_Text)
                    SetDeltaSize(textComponent, settingConfig);
                SetDefaultFont(textComponent, settingConfig);
                SetDefaultSize(textComponent, settingConfig);
                SetDefaultColor(textComponent, settingConfig);
                SetDefaultAlignment(textComponent, settingConfig);

                EditorApplication.delayCall -= OnDelayCall;
            }
        }

        private static void SetDeltaSize(TMP_Text textComponent, TextMeshProDefaultSettingConfig settingConfig)
        {
            if (textComponent == null) return;

            (textComponent.transform as RectTransform).sizeDelta = settingConfig.defaultDeltaSize;

            EditorUtility.SetDirty(textComponent);
        }

        private static void SetDefaultFont(TMP_Text textComponent, TextMeshProDefaultSettingConfig settingConfig)
        {
            if (textComponent == null) return;

            //将文本组件的字体设置为自定义默认字体
            if (settingConfig == null || settingConfig.defaultFont == null)
            {
                textComponent.font = Resources.Load<TMP_FontAsset>("Fonts & Materials/LiberationSans SDF");
                Debug.LogWarning("自定义字体为空，请检查配置文件是否正确。使用默认LiberationSans字体。");
            }
            else
            {
                textComponent.font = settingConfig.defaultFont;
            }

            EditorUtility.SetDirty(textComponent);
        }


        private static void SetDefaultColor(TMP_Text textComponent, TextMeshProDefaultSettingConfig settingConfig)
        {
            if (textComponent == null) return;

            textComponent.color = settingConfig.defaultFontColor;
            EditorUtility.SetDirty(textComponent);
        }

        private static void SetDefaultSize(TMP_Text textComponent, TextMeshProDefaultSettingConfig settingConfig)
        {
            if (textComponent == null) return;

            textComponent.fontSize = settingConfig.defaultFontSize;
            EditorUtility.SetDirty(textComponent);
        }

        private static void SetDefaultAlignment(TMP_Text textComponent, TextMeshProDefaultSettingConfig settingConfig)
        {
            if (textComponent == null) return;

            textComponent.alignment = settingConfig.defaultAlignment;
            EditorUtility.SetDirty(textComponent);
        }
    }
}
#endif
